/*
 * Copyright 2010 Christoph Widulle (christoph.widulle@googlemail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */



package com.android1.amarena2d.nodes.behavior.delegates;

import com.android1.amarena2d.commons.Tools;
import com.android1.amarena2d.engine.EngineObject;
import com.android1.amarena2d.engine.GL;
import com.android1.amarena2d.nodes.Entity;
import com.badlogic.gdx.math.Vector2;

public class DefaultTransformDelegate extends EngineObject implements TransformDelegate {

    final Entity entity;

    float scaleX = 1.0F;
    float scaleY = 1.0F;
    float scale = 1.0F;
    final Vector2 transformAnchorPos = new Vector2();
    float rotation;


    public DefaultTransformDelegate(Entity entity) {
        this.entity = entity;
    }


    //todo maybe replace by using own Matrix operations ?
    public void apply() {

        if (rotation != 0.0F || scaleX != 1.0F || scaleY != 1.0F) {

            final boolean hasTransformanchor = !(transformAnchorPos == null || Tools.isZero(transformAnchorPos));

            if (hasTransformanchor)
                GL.translate(transformAnchorPos.x, transformAnchorPos.y);


            if (scaleX != 1.0F || scaleY != 1.0F)
                GL.scale(scaleX, scaleY);

            if (rotation != 0.0F)
                GL.rotate(rotation);

            if (hasTransformanchor)
                GL.translate(-(transformAnchorPos.x), -(transformAnchorPos.y));

//                //absolute position transform
//                if (hasTransformanchor)
//                    GL.translate(transformAnchorPos.x - origion.x, transformAnchorPos.y - origion.y);
//
//                if (rotation != 0.0F)
//                    GL.rotate(rotation);
//
//                if (scaleX != 1.0F || scaleY != 1.0F)
//                    GL.scale(scaleX, scaleY);
//
//                if (hasTransformanchor)
//                    GL.translate(-(transformAnchorPos.x - origion.x), -(transformAnchorPos.y - origion.y));
        }
    }

    public boolean isTransform() {
        return rotation != 0.0F || scaleX != 1.0F || scaleY != 1.0F;
    }


    public float getScale() {
        return scale;
    }

    public boolean isScaled() {
        return scaleX != 1.0F || scaleY != 1.0F;
    }

    public void setScale(float scale) {
        this.scale = scale;
        this.scaleX = scale;
        this.scaleY = scale;
    }

    public void setScale(float scaleX, float scaleY) {
        this.scaleX = scaleX;
        this.scaleY = scaleY;
    }

    public float getScaleX() {
        return scaleX;
    }

    public void setScaleX(float scaleX) {
        this.scaleX = scaleX;
    }

    public float getScaleY() {
        return scaleY;
    }

    public void setScaleY(float scaleY) {
        this.scaleY = scaleY;
    }

    public float getTransformAnchorX() {
        return transformAnchorPos == null ? 0 : transformAnchorPos.x;
    }

    public void setTransformAnchor(float transformAnchorX, float transformAnchorY) {
        transformAnchorPos.set(transformAnchorX, transformAnchorY);
    }

    public void setTransformAnchorX(float transformAnchorX) {
        transformAnchorPos.x = transformAnchorX;
    }

    public float getTransformAnchorY() {
        return transformAnchorPos == null ? 0 : transformAnchorPos.y;
    }

    public void setTransformAnchorY(float transformAnchorY) {
        transformAnchorPos.y = transformAnchorY;
    }

    public float getRotation() {
        return rotation;
    }

    public void setRotation(float rotation) {
        this.rotation = rotation;
    }

    public void rotate(float f) {
        this.rotation = rotation + f;
    }


    public Vector2 getTransformAnchorPos() {
        return transformAnchorPos;
    }

    public void reset() {
        scaleX = 1.0F;
        scaleY = 1.0F;
        scale = 1.0F;
        transformAnchorPos.set(0, 0);
        rotation = 0.0F;
    }

    public void transformCoords(Vector2 out) {

        if (rotation == 0) {
            if (scaleX == 1 && scaleY == 1) {
                out.x = out.x - entity.getX();
                out.y = out.y - entity.getY();
            } else {
                if (transformAnchorPos.x == 0 && transformAnchorPos.y == 0) {
                    out.x = (out.x - entity.getX()) / scaleX;
                    out.y = (out.y - entity.getY()) / scaleY;
                } else {
                    out.x = out.x / scaleX - (entity.getX() - transformAnchorPos.x);
                    out.y = out.y / scaleY - (entity.getY() - transformAnchorPos.y);
                }
            }
        } else {
            final float cos = (float) Math.cos((float) Math.toRadians(rotation));
            final float sin = (float) Math.sin((float) Math.toRadians(rotation));

            if (scaleX == 1 && scaleY == 1) {
                if (transformAnchorPos.x == 0 && transformAnchorPos.y == 0) {
                    final float tox = out.x - entity.getX();
                    final float toy = out.y - entity.getY();

                    out.x = tox * cos + toy * sin;
                    out.y = tox * -sin + toy * cos;
                } else {

                    final float worldOriginX = entity.getX() + transformAnchorPos.x;
					final float worldOriginY = entity.getY() + transformAnchorPos.y;
					float fx = -transformAnchorPos.x;
					float fy = -transformAnchorPos.y;

					float x1 = cos * fx - sin * fy;
					float y1 = sin * fx + cos * fy;
					x1 += worldOriginX;
					y1 += worldOriginY;

					float tox = out.x - x1;
					float toy = out.x - y1;

					out.x = tox * cos + toy * sin;
					out.y = tox * -sin + toy * cos;


                }
            } else {
                if (transformAnchorPos.x == 0 && transformAnchorPos.y == 0) {
                    final float tox = out.x - entity.getX();
                    final float toy = out.y - entity.getY();

                    out.x = tox * cos + toy * sin;
                    out.y = tox * -sin + toy * cos;

                    out.x /= scaleX;
                    out.y /= scaleY;
                } else {
                    final float srefX = transformAnchorPos.x * scaleY;
                    final float srefY = transformAnchorPos.y * scaleX;

                    final float worldOriginX = entity.getX() + transformAnchorPos.x;
					final float worldOriginY =entity.getY()+ transformAnchorPos.y;
					float fx = -srefX;
					float fy = -srefY;

					float x1 = cos * fx - sin * fy;
					float y1 = sin * fx + cos * fy;
					x1 += worldOriginX;
					y1 += worldOriginY;

					float tox = out.x - x1;
					float toy = out.y - y1;

					out.x = tox * cos + toy * sin;
					out.y = tox * -sin + toy * cos;

					out.x /= scaleX;
					out.y /= scaleY;
                }
            }
        }
    }




}
